﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace HostFileChangerEnhanced
{
    public class HostsFileHandler
    {
        private const string hostsFileLocation = @"C:\Windows\System32\drivers\etc\hosts";
        
        public static string GetSiteIP(string domainName)
        {
            string[] hostsFileContentParts = GetHostsFilePartsWhichContainsDomainName(domainName);
            if (hostsFileContentParts == null)
                return null;

            int domainFoundInLine = GetDomainLineNumber(hostsFileContentParts, domainName);

            string domainInfoIp = GetDomainIpFromHostFileLine(hostsFileContentParts, domainFoundInLine);

            return domainInfoIp;
        }

        public static bool IsSiteInHostsFile(string domainName)
        {
            return (GetSiteIP(domainName) != null);
        }

        public static bool IsDomainIpInHostsFile(string domainName, string ipAddress)
        {
            string ipAddressOfDomainInHostsFile = GetSiteIP(domainName);
            if (ipAddressOfDomainInHostsFile == ipAddress)
                return true;

            return false;
        }

        /// <summary>
        /// Makes sure that we have the domain name in the hosts file and if it does
        /// returns the hosts file which is broken into lines
        /// </summary>
        /// <param name="domainName">domain name to check for</param>
        /// <returns>string array of hosts file lines</returns>
        private static string[] GetHostsFilePartsWhichContainsDomainName(string domainName)
        {
            string hostsFileContent = File.ReadAllText(hostsFileLocation);
            int domainStartingLocation = hostsFileContent.IndexOf(domainName);
            if (domainStartingLocation < 0)
                return null;
            /* 
             *  [19]: "#\t127.0.0.1       localhost\r"
                [20]: "#\t::1             localhost\r"
                [21]: "127.0.0.1\t"
             */
            string[] hostsFileContentParts = hostsFileContent.Split('\n');
            return hostsFileContentParts;
        }

        /// <summary>
        /// Searches and finds domain name line from the hosts file
        /// </summary>
        /// <param name="hostsFileParts">string array of hosts file lines</param>
        /// <param name="domainName">domain name to check for</param>
        /// <returns>line number where domain name resides</returns>
        private static int GetDomainLineNumber(string[] hostsFileParts, string domainName)
        {
            int domainFoundInLine = 0;
            foreach (string activeLine in hostsFileParts)
            {
                if (activeLine.Contains(domainName))
                    break;
                domainFoundInLine++;
            }

            return domainFoundInLine;
        }

        /// <summary>
        /// Finds the IP address assigned in the hosts file for the given line number
        /// </summary>
        /// <param name="hostsFileParts">string array of hosts file lines</param>
        /// <param name="lineNumber">IP adress line number</param>
        /// <returns>IP address found in the given line</returns>
        private static string GetDomainIpFromHostFileLine(string[] hostsFileParts, int lineNumber)
        {
            return hostsFileParts[lineNumber].Split('\t')[0].Split(' ')[0];
        }

        /// <summary>
        /// Changes the domainName's ip to the provided ip address
        /// </summary>
        /// <param name="domainName">domain name to work on</param>
        /// <param name="ipAdressToChangeTo">IP Address to assign to</param>
        public static void ChangeTheIpOfDomainName(string domainName, string ipAdressToChangeTo)
        {
            string[] hostsFileContentParts = GetHostsFilePartsWhichContainsDomainName(domainName);
            if (hostsFileContentParts == null)
            {
                //domain name was not in the hosts file so we are basically adding a new line
                File.AppendAllText(hostsFileLocation, "\n" + ipAdressToChangeTo + "\t" + domainName);
                return;
            }

            int domainFoundInLine = GetDomainLineNumber(hostsFileContentParts, domainName);

            string finalHostsFile = "";
            for (int temp = 0; temp < hostsFileContentParts.Length-1; temp++)
            {
                if (temp != domainFoundInLine)
                    finalHostsFile += hostsFileContentParts[temp] + "\n";
                else if (ipAdressToChangeTo != null)
                    finalHostsFile += ipAdressToChangeTo + "\t" + domainName + "\n";
            }
            finalHostsFile = finalHostsFile.TrimEnd('\n');
            File.WriteAllText(hostsFileLocation, finalHostsFile);
        }

        /// <summary>
        /// Removes the domain name from the hosts file so that it will be connected to the live DNS resolutions
        /// </summary>
        /// <param name="domainName">domain name to work on</param>
        public static void RemoveDomainNameFromHostFile(string domainName)
        {
            ChangeTheIpOfDomainName(domainName, null);
        }
    }
}
